package framework.reflectasm;

import com.esotericsoftware.reflectasm.FieldAccess;
import com.esotericsoftware.reflectasm.MethodAccess;
import com.me.common.pojo.Student;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.time.LocalDate;

/**
 * ReflectASM API 测试
 */
public class ReflectASMTests {

    private static final int COUNT = 100000000;
    private static final Student STUDENT1 = new Student();
    private static final LocalDate LOCAL_DATE = LocalDate.of(1992, 2, 17);
    private static final Student STUDENT2 = new Student("ljy", 18, LOCAL_DATE);;

    public static void main(String[] args) throws Exception {
        // 方法调用测试
        System.out.println("==========方法调用测试");
        testReflectAsm4Name();
        testReflectAsm4Index();
        testJdkMethod();

    }

    /**
     * reflectasm：方法名 调用方法
     */
    private static void testReflectAsm4Name() {
        // 生成字节码的方式创建 StudentMethodAccess
        MethodAccess access = MethodAccess.get(Student.class);

        long start = System.currentTimeMillis();
        for (int i = 0; i < COUNT; i++) {
            access.invoke(STUDENT1, "setBirthday", LOCAL_DATE);
        }
        System.out.println("timeout=" + (System.currentTimeMillis() - start) + "ms");
    }

    /**
     * reflectasm：下标 调用方法
     */
    private static void testReflectAsm4Index() {
        // 生成字节码的方式创建 StudentMethodAccess
        MethodAccess access = MethodAccess.get(Student.class);

        long start = System.currentTimeMillis();
        int index = access.getIndex("setBirthday", LocalDate.class);
        for (int i = 0; i < COUNT; i++) {
            access.invoke(STUDENT1, index, LOCAL_DATE);
        }
        System.out.println("timeout=" + (System.currentTimeMillis() - start) + "ms");
    }

    /**
     * reflectasm set属性值
     */
    private static void fieldAccessSetter() throws Exception {
        Field field = Student.class.getDeclaredField("birthday");
        field.setAccessible(true);
        FieldAccess fieldAccess = FieldAccess.get(Student.class);
        int index = fieldAccess.getIndex(field);

        long start = System.currentTimeMillis();
        for (int i = 0; i < COUNT; i++) {
            fieldAccess.set(STUDENT1, "birthday", LOCAL_DATE);
        }
        System.out.println("timeout=" + (System.currentTimeMillis() - start) + "ms");
    }

    /**
     * reflectasm get属性值
     */
    private static void fieldAccessGetter() {
        FieldAccess fieldAccess = FieldAccess.get(Student.class);

        long start = System.currentTimeMillis();
        for (int i = 0; i < COUNT; i++) {
            fieldAccess.get(STUDENT2, "birthday");
        }
        System.out.println("timeout=" + (System.currentTimeMillis() - start));

        System.out.println(fieldAccess.get(STUDENT2, "birthday"));
    }

    /**
     * JDK反射 调用方法
     */
    private static void testJdkMethod() throws Exception {
        Method method = Student.class.getMethod("setBirthday", LocalDate.class);

        long start = System.currentTimeMillis();
        for (int i = 0; i < COUNT; i++) {
            method.invoke(STUDENT1, LOCAL_DATE);
        }
        System.out.println("timeout=" + (System.currentTimeMillis() - start) + "ms");
    }

    /**
     * JDK反射 set属性值
     */
    private static void jdkFieldSetter() throws Exception {
        Field field = Student.class.getField("birthday");

        long start = System.currentTimeMillis();
        for (int i = 0; i < COUNT; i++) {
            field.set(STUDENT1, LOCAL_DATE);
        }
        System.out.println("timeout=" + (System.currentTimeMillis() - start) + "ms");
    }

    /**
     * JDK反射 get属性值
     */
    private static void jdkFieldGetter() throws Exception {
        Field field = Student.class.getField("birthday");
        field.setAccessible(true);

        long start = System.currentTimeMillis();
        for (int i = 0; i < COUNT; i++) {
            field.get(STUDENT2);
        }
        System.out.println("timeout=" + (System.currentTimeMillis() - start) + "ms");

        System.out.println(field.get(STUDENT2));
    }

}
